package life.mahu.community.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import life.mahu.community.exception.CustomizeErrorCode;
import life.mahu.community.dto.PaginationDTO;
import life.mahu.community.dto.QuestionDTO;
import life.mahu.community.dto.QuestionQueryDTO;
import life.mahu.community.enums.SortEnum;
import life.mahu.community.exception.CustomizeException;
import life.mahu.community.mapper.*;
import life.mahu.community.model.*;
import life.mahu.community.model.*;
import life.mahu.community.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class QuestionService {

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionExtMapper questionExtMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserQuestionMapper userQMapper;

    @Autowired
    private CommentService commentService;

    @Autowired
    private UserCommentMapper userCMapper;

    @Resource
    private RedisUtil redis;

    // redis中存储的过期时间s
    private static int ExpireTime = 60 * 60;

    public PaginationDTO list(String search, String tag, Integer categoryId, String sort, Integer page, Integer size) {

        if (StringUtils.isNotBlank(search)) {
            String[] tags = StringUtils.split(search, " ");
            search = Arrays
                    .stream(tags)
                    .filter(StringUtils::isNotBlank)
                    .map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining("|"));
        }

        PaginationDTO paginationDTO = new PaginationDTO();

        Integer totalPage;

        QuestionQueryDTO questionQueryDTO = new QuestionQueryDTO();
        questionQueryDTO.setSearch(search);
        if (StringUtils.isNotBlank(tag)) {
            tag = tag.replace("+", "").replace("*", "").replace("?", "");
            questionQueryDTO.setTag(tag);
        }

        for (SortEnum sortEnum : SortEnum.values()) {
            if (sortEnum.name().toLowerCase().equals(sort)) {
                questionQueryDTO.setSort(sort);

                if (sortEnum == SortEnum.HOT7) {
                    questionQueryDTO.setTime(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 7);
                }
                if (sortEnum == SortEnum.HOT30) {
                    questionQueryDTO.setTime(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30);
                }
                break;
            }
        }

        if (categoryId != 0) {
            questionQueryDTO.setCategoryId(categoryId);
        }

        Integer totalCount = questionExtMapper.countBySearch(questionQueryDTO);

        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }

        if (page < 1) {
            page = 1;
        }
        if (page > totalPage) {
            page = totalPage;
        }

        paginationDTO.setPagination(totalPage, page);
        Integer offset = page < 1 ? 0 : size * (page - 1);
        questionQueryDTO.setSize(size);
        questionQueryDTO.setPage(offset);
        List<Question> questions = questionExtMapper.selectBySearch(questionQueryDTO);
        List<QuestionDTO> questionDTOList = new ArrayList<>();

        for (Question question : questions) {
            User user = userMapper.selectByPrimaryKey(question.getCreator());
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(question, questionDTO);
            questionDTO.setUser(user);
            questionDTOList.add(questionDTO);
        }

        paginationDTO.setData(questionDTOList);
        return paginationDTO;
    }

    public PaginationDTO list(Long userId, Integer page, Integer size, Integer type) {
        PaginationDTO paginationDTO = new PaginationDTO();
        Integer totalPage;
        Integer totalCount;
        List<UserQuestion> userQuestions = null;
        List<QuestionDTO> questionDTOList = new ArrayList<>();
        if (type == 1) {
            UserQuestionExample UQExample = new UserQuestionExample();
            UserQuestionExample.Criteria criteria = UQExample.createCriteria();
            criteria.andUserIdEqualTo(userId);
            userQuestions = userQMapper.selectByExample(UQExample);
            totalCount = userQuestions.size();
        } else {
            QuestionExample questionExample = new QuestionExample();
            questionExample.createCriteria()
                    .andCreatorEqualTo(userId);
            totalCount = (int) questionMapper.countByExample(questionExample);
        }
        if (totalCount > 0) {//如果没有记录的话后面的分页也就没必要做了
            if (totalCount % size == 0) {
                totalPage = totalCount / size;
            } else {
                totalPage = totalCount / size + 1;
            }

            if (page < 1) {
                page = 1;
            }
            if (page > totalPage) {
                page = totalPage;
            }

            paginationDTO.setPagination(totalPage, page);

            //size*(page-1)
            Integer offset = size * (page - 1);
            QuestionExample example = new QuestionExample();
            if (type == 1) {
                List<Long> ids = new ArrayList<Long>(userQuestions.size());
                for (int i = 0, length = userQuestions.size(); i < length; i++) {
                    ids.add(userQuestions.get(i).getQuestionId());
                }
                example.createCriteria()
                        .andIdIn(ids);
            } else
                example.createCriteria()
                        .andCreatorEqualTo(userId);
            List<Question> questions = questionMapper.selectByExampleWithRowbounds(example, new RowBounds(offset, size));
            for (Question question : questions) {
                User user = userMapper.selectByPrimaryKey(question.getCreator());
                QuestionDTO questionDTO = new QuestionDTO();
                BeanUtils.copyProperties(question, questionDTO);
                questionDTO.setUser(user);
                questionDTOList.add(questionDTO);
            }
        }
        paginationDTO.setData(questionDTOList);
        return paginationDTO;
    }

    public QuestionDTO getById(Long id) {
        Question question = questionMapper.selectByPrimaryKey(id);
        if (question == null) {
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        QuestionDTO questionDTO = new QuestionDTO();
        BeanUtils.copyProperties(question, questionDTO);
        User user = userMapper.selectByPrimaryKey(question.getCreator());
        questionDTO.setUser(user);
        return questionDTO;
    }

    public void createOrUpdate(Question question, String tag) {
        if (question.getId() == null) {
            // 创建
            question.setGmtCreate(System.currentTimeMillis());
            question.setGmtModified(question.getGmtCreate());
            question.setViewCount(0);
            question.setLikeCount(0);
            question.setCommentCount(0);
            question.setTag(tag);
            int questionId = questionMapper.insert(question);
        } else {
            // 更新

            Question dbQuestion = questionMapper.selectByPrimaryKey(question.getId());
            if (dbQuestion == null) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }

            if (dbQuestion.getCreator().longValue() != question.getCreator().longValue()) {
                throw new CustomizeException(CustomizeErrorCode.INVALID_OPERATION);
            }

            Question updateQuestion = new Question();
            updateQuestion.setGmtModified(System.currentTimeMillis());
            updateQuestion.setTitle(question.getTitle());
            updateQuestion.setDescription(question.getDescription());
            updateQuestion.setTag(question.getTag());
            updateQuestion.setCid(question.getCid());
            QuestionExample example = new QuestionExample();
            example.createCriteria()
                    .andIdEqualTo(question.getId());
            int updated = questionMapper.updateByExampleSelective(updateQuestion, example);
            if (updated != 1) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
        }
    }

    public void incView(Long id) {
        Question question = new Question();
        question.setId(id);
        question.setViewCount(1);
        questionExtMapper.incView(question);
    }

    public List<QuestionDTO> selectRelated(QuestionDTO queryDTO) {
        if (StringUtils.isBlank(queryDTO.getTag())) {
            return new ArrayList<>();
        }
        String[] tags = StringUtils.split(queryDTO.getTag(), ",");
        String regexpTag = Arrays
                .stream(tags)
                .filter(StringUtils::isNotBlank)
                .map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.joining("|"));
        Question question = new Question();
        question.setId(queryDTO.getId());
        question.setTag(regexpTag);

        List<Question> questions = questionExtMapper.selectRelated(question);
        List<QuestionDTO> questionDTOS = questions.stream().map(q -> {
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(q, questionDTO);
            return questionDTO;
        }).collect(Collectors.toList());
        return questionDTOS;
    }

    public boolean insertOrUpdateUQ(UserQuestion userQ, Integer type) {
        UserQuestionExample UQExample = new UserQuestionExample();
        UserQuestionExample.Criteria criteria = UQExample.createCriteria();

        criteria.andUserIdEqualTo(userQ.getUserId());
        if (userQ.getQuestionId() != 0) {
            criteria.andQuestionIdEqualTo(userQ.getQuestionId());
        }

        //更新数据库及缓存
        List<UserQuestion> userQuestions = userQMapper.selectByExample(UQExample);//查找该用户是否关注了此问题
        if (type == 1) {//关注
            if (userQuestions.size() != 0) {//如果数据库里已经有了的话说明系统逻辑错误
                return false;
            } else {//正常则更新数据库及缓存
                userQMapper.insert(userQ);
                redis.listLSet("muhuQuestionUserId=" + userQ.getUserId(), userQ.getQuestionId(), ExpireTime);
            }
        } else {//取关
            if (userQuestions.size() != 0) {//正常则更新数据库及缓存
                userQMapper.deleteByExample(UQExample);
                redis.lRemove("muhuQuestionUserId=" + userQ.getUserId(), 1, userQ.getQuestionId());
            } else {//如果数据库里没有的话说明系统逻辑错误
                return false;
            }
        }

        //更新Question的like_count字段
        Question question = new Question();
        question.setId(userQ.getQuestionId());
        question.setLikeCount(type);
        questionExtMapper.incLikeCount(question);

        //关注通知
        if (type == 1) {

        }

        return true;

    }

    public List<Long> listByUserID(Long id) {
        UserQuestionExample UQExample = new UserQuestionExample();
        UQExample.createCriteria().andUserIdEqualTo(id);

        List<Long> list = new ArrayList<>();
        List<UserQuestion> userQuestionslist = userQMapper.selectByExample(UQExample);
        for (UserQuestion userQuestion : userQuestionslist) {
            list.add(userQuestion.getQuestionId());
        }
        return list;
    }

    public Boolean delQuestionById(Long id) {
        int delUser = questionMapper.deleteByPrimaryKey(id);
        return delUser > -1 ? true : false;
    }

    public PageInfo getQuestionListPage(Question question, Integer page, Integer limit, String keyword) {
        QuestionExample questionExample = new QuestionExample();
        QuestionExample.Criteria criteria = questionExample.createCriteria();
        QuestionExample questionExample2 = new QuestionExample();
        QuestionExample.Criteria criteria2 = questionExample.createCriteria();
        if (!(question.getUname() == null || "".equals(question.getUname()))) {
            UserExample userExample = new UserExample();
            UserExample.Criteria userCriteria = userExample.createCriteria();
            userCriteria.andNameLike("%" + question.getUname() + "%");
            List<User> users = userMapper.selectByExample(userExample);
            List<Long> userIds = new ArrayList<>();
            for (User user : users) {
                userIds.add(user.getId());
            }
            criteria.andCreatorIn(userIds);
            criteria2.andCreatorIn(userIds);
        }
        if (question.getCid() != null && question.getCid() != 0) {
            criteria.andCidEqualTo(question.getCid());
            criteria2.andCidEqualTo(question.getCid());
        }
        if (!(question.getTag() == null || "".equals(question.getTag()))) {
            criteria.andTagLike("%" + question.getTag() + "%");
            criteria2.andTagLike("%" + question.getTag() + "%");
        }
        List<Question> questions;
        if (!(keyword == null || "".equals(keyword))) {
            criteria.andTitleLike("%" + keyword + "%");
            criteria2.andDescriptionLike("%" + keyword + "%");
            questionExample.or(criteria2);
        }
        PageHelper.startPage(page, limit);
        questions = questionMapper.selectByExampleGetALL(questionExample);

        return new PageInfo<Question>(questions);
    }

    public Question getQuestionById(Long id) {
        return questionMapper.selectByPrimaryKeyGetALL(id);
    }

    public Boolean insertQuestion(Question question) {
        question.setGmtCreate(System.currentTimeMillis());
        question.setGmtModified(System.currentTimeMillis());
        question.setCreator(1L);
        int insert = questionMapper.insert(question);
        return insert > 0 ? true : false;
    }

    public Boolean updateQuestionById(Question question) {
        Question loseQuestion = questionMapper.selectByPrimaryKey(question.getId());
        question.setGmtModified(System.currentTimeMillis());
        question.setGmtCreate(loseQuestion.getGmtCreate());
        int update = questionMapper.updateByPrimaryKey(question);
        return update > 0 ? true : false;
    }

    //较完整的删除，删除问题的同时删除评论和点赞
    public Integer deleteQuestionById(Long id) {
        //--------------------------------------
        List<Long> comIds=commentService.queryByParentId(id);//获取该问题下所有评论Id
        if(comIds.size()>0){
            UserCommentExample UCExample = new UserCommentExample();
            UCExample.createCriteria().andCommentIdIn(comIds);
            userCMapper.deleteByExample(UCExample);//删除评论对应的点赞
            //--------------------------------------
            commentService.delCommentByParentId(id);//删除问题对应的评论
        }
        //--------------------------------------
        UserQuestionExample UQExample = new UserQuestionExample();
        UQExample.createCriteria().andQuestionIdEqualTo(id);
        userQMapper.deleteByExample(UQExample);//删除问题对应的收藏
        //--------------------------------------
        questionMapper.deleteByPrimaryKey(id);//删除问题
        return 1;
    }
}
